package com.tabjin.rfidsocket.service.sys.impl;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.google.common.base.Preconditions;
import com.google.common.collect.Lists;
import com.tabjin.rfidsocket.common.RequestHolder;
import com.tabjin.rfidsocket.common.utils.BeanValidator;
import com.tabjin.rfidsocket.common.utils.PagedGridResult;
import com.tabjin.rfidsocket.exception.ParamException;
import com.tabjin.rfidsocket.mapper.mapper.SysAclCustomMapper;
import com.tabjin.rfidsocket.mapper.mapper.SysAclMapper;
import com.tabjin.rfidsocket.pojo.SysAcl;
import com.tabjin.rfidsocket.pojo.bo.SysAclBO;
import com.tabjin.rfidsocket.pojo.vo.SysAclVO;
import com.tabjin.rfidsocket.service.sys.SysAclService;
import org.apache.commons.collections4.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

/**
 * @author tabjin
 * create at 2020/12/23 14:55
 * @program rfid_socket
 * @description 权限点
 */
@Service
public class SysAclServiceImpl implements SysAclService {

    static final Logger logger = LoggerFactory.getLogger(SysAclServiceImpl.class);

    @Autowired
    private SysAclMapper sysAclMapper;

    @Autowired
    private SysAclCustomMapper sysAclCustomMapper;

    /**
     * 新增权限点
     *
     * @param sysAclBO 权限点BO
     * @return
     */
    @Transactional(propagation = Propagation.REQUIRED)
    @Override
    public SysAclVO add(SysAclBO sysAclBO) {
        BeanValidator.check(sysAclBO);
        // 同一权限模块下是否存在相同名称的权限点
        if (checkExist(sysAclBO.getAclModuleId(), sysAclBO.getName(), sysAclBO.getId())) {
            logger.error("新增权限点 同一权限模块下存在相同名称的权限点");
            throw new ParamException("新增权限点 同一权限模块下存在相同名称的权限点");
        }

        SysAcl sysAcl = SysAcl.builder()
                .name(sysAclBO.getName())
                .aclModuleId(sysAclBO.getAclModuleId())
                .url(sysAclBO.getUrl())
                .type(sysAclBO.getType())
                .status(sysAclBO.getStatus())
                .seq(sysAclBO.getSeq())
                .remark(sysAclBO.getRemark())
                .build();
        sysAcl.setCode(generateCode());// 每个权限点都有唯一的code值
        sysAcl.setOperator(RequestHolder.getCurrentUser().getUsername());
        sysAcl.setOperateIp("127.0.0.1");
        sysAcl.setOperateTime(new Date());

        sysAclMapper.insertSelective(sysAcl);

        SysAclVO vo = new SysAclVO();
        BeanUtils.copyProperties(sysAcl, vo);
        return vo;
    }

    /**
     * 更新权限点
     *
     * @param sysAclBO 权限点BO
     * @return
     */
    @Transactional(propagation = Propagation.REQUIRED)
    @Override
    public SysAclVO update(SysAclBO sysAclBO) {
        BeanValidator.check(sysAclBO);
        if (checkExist(sysAclBO.getAclModuleId(), sysAclBO.getName(), sysAclBO.getId())) {
            logger.error("更新权限点 同一权限模块下存在相同名称的权限点");
            throw new ParamException("更新权限点 同一权限模块下存在相同名称的权限点");
        }

        // 这边before预留给日志记录
        SysAcl before = sysAclMapper.selectByPrimaryKey(sysAclBO.getId());
        Preconditions.checkNotNull(before, "待更新的权限点为空");

        SysAcl after = SysAcl.builder()
                .id(sysAclBO.getId())
                .name(sysAclBO.getName())
                .aclModuleId(sysAclBO.getAclModuleId())
                .url(sysAclBO.getUrl())
                .type(sysAclBO.getType())
                .status(sysAclBO.getStatus())
                .seq(sysAclBO.getSeq())
                .remark(sysAclBO.getRemark())
                .build();
        // 更新时权限点code码不做更改
        after.setOperator(RequestHolder.getCurrentUser().getUsername());
        after.setOperateIp("127.0.0.1");
        after.setOperateTime(new Date());

        sysAclMapper.updateByPrimaryKey(after);

        SysAclVO vo = new SysAclVO();
        BeanUtils.copyProperties(after, vo);
        return vo;
    }

    /**
     * 根据权限模块获取权限点
     *
     * @param sysAclModuleId 权限模块id
     * @param page           第几页
     * @param pageSize       每页显示条数
     * @return
     */
    @Transactional(propagation = Propagation.SUPPORTS)
    @Override
    public PagedGridResult searchAclModuleItems(Integer sysAclModuleId,
                                                Integer page,
                                                Integer pageSize) {
//        BeanValidator.check(sysAclModuleId);
//        Integer count = sysAclCustomMapper.countByAclModuleId(sysAclModuleId);
//        if (count > 0) {
//
//        }
        PageHelper.startPage(page, pageSize);
        List<SysAclVO> list = sysAclCustomMapper.searchAclModuleItems(sysAclModuleId);
        return setPagesGrid(list, page);
    }

    /**
     * 批量获取权限模块的权限点
     *
     * @param sysAclModuleIds
     * @return
     */
    @Transactional(propagation = Propagation.SUPPORTS)
    @Override
    public List<SysAclVO> searchAclModuleItemsWithoutPaged(List<Integer> sysAclModuleIds) {
        if (CollectionUtils.isEmpty(sysAclModuleIds)) {
            return Lists.newArrayList();
        }
        return sysAclCustomMapper.searchAclModuleItemsWithoutPaged(sysAclModuleIds);
    }

    @Override
    public Integer countByAclModuleId(Integer sysAclModuleId) {
        return null;
    }

    /**
     * 同一权限模块下是否存在相同名称的权限点
     *
     * @param aclModuleId 权限模块id
     * @param name        权限点名称
     * @param id          权限点id
     * @return
     */
    private boolean checkExist(Integer aclModuleId, String name, Integer id) {
        return sysAclCustomMapper.countByNameAndAclModuleId(aclModuleId, name, id) > 0;
    }

    private static String generateCode() {
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHmmss");
        String s = dateFormat.format(new Date()) + "_" + (int) (Math.random() * 100);
        return s;
    }

    /**
     * 封装分页助手
     *
     * @param list
     * @param page
     * @return
     */
    private PagedGridResult setPagesGrid(List<?> list, Integer page) {
        PageInfo pageList = new PageInfo<>(list);
        PagedGridResult grid = new PagedGridResult();
        grid.setPage(page);
        grid.setRows(list);
        grid.setTotal(pageList.getPages());
        grid.setRecords(pageList.getTotal());
        return grid;
    }
}
